home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / SOCKET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-28  |  34.2 KB  |  1,530 lines

  1. #include <stdio.h>
  2. #ifdef    __STDC__
  3. #include <stdarg.h>
  4. #endif
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "netuser.h"
  8. #include "timer.h"
  9. #include "iface.h"
  10. #include "ip.h"
  11. #include "tcp.h"
  12. #include "udp.h"
  13. #include "ax25.h"
  14. #include "lapb.h"
  15. #include "proc.h"
  16. #include "usock.h"
  17. #include "socket.h"
  18. #include "config.h"
  19.  
  20. extern int errno;
  21. extern char *Tcpstates[],*Tcpreasons[],*Axreasons[];
  22. extern char *Ax25states[];
  23. extern char *pinet();
  24. extern int32 Ip_addr;
  25. extern int16 Lport;
  26. void s_arcall(),s_atcall(),s_ascall(),rip_recv();
  27. static void s_trcall(),s_ttcall(),s_tscall(),s_urcall(),trdiscard();
  28. static int checkaddr();
  29. static void autobind();
  30. extern struct usock *itop();
  31.  
  32. char *Socktypes[] = {
  33.     "Not Used",
  34.     "TCP",
  35.     "UDP",
  36.     "AX25 I",
  37.     "AX25 UI",
  38.     "Raw IP"
  39. };
  40. char  Badsocket[] = "Bad socket";
  41. struct usock *Usock;        /* Socket entry array */
  42. int Nusock = DEFNSOCK;        /* Number of socket entries */
  43.  
  44. /* The following two variables are needed because there can be only one
  45.  * socket listening on each of the AX.25 modes (I and UI)
  46.  */
  47. #ifdef    AX25
  48. int axi_sock = -1;    /* Socket number listening for AX25 connections */
  49. int axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  50. struct mbuf *bcq;    /* Queue of incoming UI frames */
  51.  
  52. /* Function that handles incoming UI frames from lapb.c */
  53. void
  54. beac_input(iface,src,bp)
  55. struct iface *iface;
  56. struct ax25_addr *src;
  57. struct mbuf *bp;
  58. {
  59.     struct mbuf *hdr;
  60.     struct sockaddr_ax *sax;
  61.  
  62.     if(axui_sock == -1){
  63.         /* Nobody there to read it */
  64.         free_p(bp);
  65.     } else {
  66.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  67.             free_p(bp);
  68.             return;
  69.         }
  70.         sax = (struct sockaddr_ax *)hdr->data;
  71.         sax->sax_family = AF_AX25;
  72.         memcpy((char *)&sax->ax25_addr,(char *)src,sizeof(struct ax25_addr));
  73.         strncpy((char *)&sax->iface,iface->name,ILEN);
  74.         hdr->next = bp;
  75.         enqueue(&bcq,hdr);
  76.     }
  77. }
  78. #endif
  79.  
  80. /* Initialize user socket array */
  81. void
  82. sockinit()
  83. {
  84.     if(Usock != (struct usock *)NULL)
  85.         return;    /* Already initialized */
  86.     Usock = (struct usock *)calloc(Nusock,sizeof(struct usock));
  87. }
  88.  
  89. /* Create a user socket, return socket index
  90.  * The mapping to actual protocols is as follows:
  91.  *        
  92.  *        
  93.  * ADDRESS FAMILY    Stream        Datagram    Raw
  94.  *
  95.  * AF_INET        TCP        UDP        IP
  96.  * AF_AX25        I-frames    UI-frames
  97.  */
  98. int
  99. socket(af,type,protocol)
  100. int af;        /* Address family */
  101. int type;    /* Stream or datagram */
  102. int protocol;    /* Used for raw IP sockets */
  103. {
  104.     register struct usock *up;
  105.     int s;
  106.  
  107.     for(up=Usock;up < &Usock[Nusock];up++)
  108.         if(up->type == NOTUSED)
  109.             break;
  110.  
  111.     if(up == &Usock[Nusock]){
  112.         /* None left */
  113.         errno = EMFILE;
  114.         return -1;
  115.     }
  116.     s = up - Usock;
  117.     errno = 0;
  118.     up->noblock = 0;
  119.     up->rdysock = -1;
  120.     up->cb.p = NULLCHAR;
  121.     up->peername = up->name = NULLCHAR;
  122.     up->namelen = up->peernamelen = 0;
  123.     up->owner = Curproc;
  124.     memset(up->errcodes,0,sizeof(up->errcodes));
  125.     switch(af){
  126. #ifdef    AX25
  127.     case AF_AX25:
  128.         switch(type){
  129.         case SOCK_STREAM:
  130.             up->type = TYPE_AX25I;
  131.             break;
  132.         case SOCK_DGRAM:
  133.             up->type = TYPE_AX25UI;
  134.             break;
  135.         default:
  136.             errno = ESOCKTNOSUPPORT;
  137.             break;
  138.         }
  139.         break;
  140. #endif
  141.     case AF_INET:
  142.         switch(type){
  143.         case SOCK_STREAM:
  144.             up->type = TYPE_TCP;
  145.             break;
  146.         case SOCK_DGRAM:
  147.             up->type = TYPE_UDP;
  148.             break;
  149.         case SOCK_RAW:
  150.             up->type = TYPE_RAW;
  151.             up->cb.rip = raw_ip(protocol,rip_recv);
  152.             up->cb.rip->user = s;
  153.             break;
  154.         default:
  155.             errno = ESOCKTNOSUPPORT;
  156.             break;
  157.         }
  158.         break;
  159.     default:
  160.         errno = EAFNOSUPPORT;
  161.         break;
  162.     }
  163.     if(errno)
  164.         return -1;
  165.  
  166.     return s;
  167. }
  168.  
  169. /* Attach a local address/port to a socket. If not issued before a connect
  170.  * or listen, will be issued automatically
  171.  */
  172. int
  173. bind(s,name,namelen)
  174. int s;        /* Socket index */
  175. char *name;    /* Local name */
  176. int namelen;    /* Length of name */
  177. {
  178.     register struct usock *up;
  179.     union sp local;
  180.     struct socket lsock;
  181.  
  182.     if((up = itop(s)) == NULLUSOCK){
  183.         errno = EBADF;
  184.         return -1;
  185.     }
  186.     if(name == NULLCHAR){
  187.         errno = EFAULT;
  188.         return -1;
  189.     }
  190.     if(up->name != NULLCHAR){
  191.         /* Bind has already been issued */
  192.         errno = EINVAL;
  193.         return -1;
  194.     }
  195.     if(checkaddr(up->type,name,namelen) == -1){
  196.         /* Incorrect length or family for chosen protocol */
  197.         errno = EAFNOSUPP;
  198.         return -1;    
  199.     }
  200.     /* Stash name in an allocated block */
  201.     up->namelen = namelen;
  202.     up->name = malloc(namelen);
  203.     memcpy(up->name,name,namelen);
  204.     /* Create control block for datagram sockets */
  205.     switch(up->type){
  206.     case TYPE_UDP:
  207.         local.in = (struct sockaddr_in *)up->name;
  208.         lsock.address = local.in->sin_addr.s_addr;
  209.         lsock.port = local.in->sin_port;
  210.         up->cb.udp = open_udp(&lsock,s_urcall);
  211.         up->cb.udp->user = s;
  212.         break;
  213. #ifdef    AX25
  214.     case TYPE_AX25UI:
  215.         if(axui_sock != -1){
  216.             errno = EADDRINUSE;
  217.             return -1;
  218.         }
  219.         axui_sock = s;
  220.         break;
  221. #endif
  222.     }
  223.     return 0;
  224. }
  225. /* Post a listen on a socket */
  226. int
  227. listen(s,backlog)
  228. int s;        /* Socket index */
  229. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  230. {
  231.     register struct usock *up;
  232.     union sp local;
  233.     struct socket lsock;
  234.  
  235.     if((up = itop(s)) == NULLUSOCK){
  236.         errno = EBADF;
  237.         return -1;
  238.     }
  239.     if(up->cb.p != NULLCHAR){
  240.         errno = EISCONN;
  241.         return -1;
  242.     }
  243.     switch(up->type){
  244.     case TYPE_TCP:
  245.         if(up->name == NULLCHAR)
  246.             autobind(s,AF_INET);
  247.  
  248.         local.in = (struct sockaddr_in *)up->name;
  249.         lsock.address = local.in->sin_addr.s_addr;
  250.         lsock.port = local.in->sin_port;
  251.         up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  252.          backlog ? TCP_SERVER:TCP_PASSIVE,0,
  253.         s_trcall,s_ttcall,s_tscall,0,s);
  254.         break;
  255.     case TYPE_AX25I:
  256.         if(up->name == NULLCHAR)
  257.             autobind(s,AF_AX25);
  258.         
  259.         break;    /* TO BE IMPLEMENTED */
  260.     default:
  261.         /* Listen not supported on datagram sockets */
  262.         errno = EOPNOTSUPP;
  263.         return -1;        
  264.     }
  265.     return 0;
  266. }
  267. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  268. int
  269. connect(s,peername,peernamelen)
  270. int s;            /* Socket index */
  271. char *peername;        /* Peer name */
  272. int peernamelen;    /* Length of peer name */
  273. {
  274.     register struct usock *up;
  275.     union cb cb;
  276.     union sp local,remote;
  277.     struct socket lsock,fsock;
  278.     struct iface *iface;
  279.  
  280.     if((up = itop(s)) == NULLUSOCK){
  281.         errno = EBADF;
  282.         return -1;
  283.     }
  284.     if(peername == NULLCHAR){
  285.         /* Connect must specify a remote address */
  286.         errno = EFAULT;
  287.         return -1;
  288.     }
  289.     if(checkaddr(up->type,peername,peernamelen) == -1){
  290.         errno = EAFNOSUPPORT;
  291.         return -1;
  292.     }
  293.     /* Raw socket control blocks are created in socket() */
  294.     if(up->type != TYPE_RAW && up->cb.p != NULLCHAR){
  295.         errno = EISCONN;
  296.         return -1;
  297.     }
  298.     if((up->peername = malloc(peernamelen)) == NULLCHAR){
  299.         errno = ENOMEM;
  300.         return -1;
  301.     }
  302.     memcpy(up->peername,peername,peernamelen);
  303.     up->peernamelen = peernamelen;
  304.  
  305.     /* Set up the local socket structures for TCP and UDP */
  306.     if(up->name == NULLCHAR){
  307.         switch(up->type){
  308.         case TYPE_TCP:
  309.         case TYPE_UDP:
  310.         case TYPE_RAW:
  311.             autobind(s,AF_INET);
  312.             break;
  313.         case TYPE_AX25I:
  314.         case TYPE_AX25UI:
  315.             autobind(s,AF_AX25);
  316.             break;
  317.         }
  318.     }
  319.     switch(up->type){
  320.     case TYPE_TCP:
  321.         /* Construct the TCP-style ports from the sockaddr structs */
  322.         local.in = (struct sockaddr_in *)up->name;
  323.         lsock.address = local.in->sin_addr.s_addr;
  324.         lsock.port = local.in->sin_port;
  325.  
  326.         remote.in = (struct sockaddr_in *)up->peername;
  327.         fsock.address = remote.in->sin_addr.s_addr;
  328.         fsock.port = remote.in->sin_port;
  329.  
  330.         /* Open the TCB in active mode */
  331.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  332.          s_trcall,s_ttcall,s_tscall,0,s);
  333.  
  334.         /* Wait for the connection to complete */
  335.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != ESTABLISHED){
  336.             if(up->noblock){
  337.                 errno = EWOULDBLOCK;
  338.                 return -1;
  339.             } else if(pwait(up) != 0){
  340.                 errno = EINTR;
  341.                 return -1;
  342.             }
  343.         }
  344.         if(cb.tcb == NULLTCB){
  345.             /* Probably got refused */
  346.             free(up->peername);
  347.             up->peername = NULLCHAR;
  348.             errno = ECONNREFUSED;
  349.             return -1;
  350.         }
  351.         break;
  352.     case TYPE_UDP:
  353.     case TYPE_AX25UI:
  354.     case TYPE_RAW:
  355.         /* Control block already created by bind() */
  356.         break;
  357. #ifdef    AX25
  358.     case TYPE_AX25I:
  359.         local.ax = (struct sockaddr_ax *)up->name;
  360.         remote.ax = (struct sockaddr_ax *)up->peername;
  361.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  362.             errno = EINVAL;
  363.             return -1;
  364.         }
  365.         up->cb.ax25 = open_ax25(iface,
  366.          (struct ax25_addr *)&local.ax->ax25_addr,
  367.          (struct ax25_addr *)&remote.ax->ax25_addr,
  368.          2048,s_arcall,s_atcall,s_ascall,s);
  369.  
  370.         /* Wait for the connection to complete */
  371.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != CONNECTED){
  372.             if(up->noblock){
  373.                 errno = EWOULDBLOCK;
  374.                 return -1;
  375.             } else if(pwait(up) != 0){
  376.                 errno = EINTR;
  377.                 return -1;
  378.             }
  379.         }
  380.         if(cb.ax25 == NULLAX25){
  381.             /* Connection probably already exists */
  382.             free(up->peername);
  383.             up->peername = NULLCHAR;
  384.             errno = ECONNREFUSED;
  385.             return -1;
  386.         }
  387.         break;
  388. #endif
  389.     }
  390.     return 0;
  391. }
  392. /* Wait for a connection. Valid only for connection-oriented sockets. */
  393. int
  394. accept(s,peername,peernamelen)
  395. int s;            /* Socket index */
  396. char *peername;        /* Peer name */
  397. int *peernamelen;    /* Length of peer name */
  398. {
  399.     int i;
  400.     register struct usock *up;
  401.  
  402.     if((up = itop(s)) == NULLUSOCK){
  403.         errno = EBADF;
  404.         return -1;
  405.     }
  406.     if(up->cb.p == NULLCHAR){
  407.         errno = EOPNOTSUPP;
  408.         return -1;
  409.     }
  410.     /* Accept is valid only for stream sockets */
  411.     switch(up->type){
  412.     case TYPE_TCP:
  413.     case TYPE_AX25I:
  414.         break;
  415.     default:
  416.         errno = EOPNOTSUPP;
  417.         return -1;
  418.     }    
  419.     /* Wait for the state-change upcall routine to signal us */
  420.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  421.         if(up->noblock){
  422.             errno = EWOULDBLOCK;
  423.             return -1;
  424.         } else if(pwait(up) != 0){
  425.             errno = EINTR;
  426.             return -1;
  427.         }
  428.     }
  429.     if(up->cb.p == NULLCHAR){
  430.         /* Blown away */
  431.         errno = EBADF;
  432.         return -1;
  433.     }
  434.     i = up->rdysock;
  435.     up->rdysock = -1;
  436.  
  437.     up = &Usock[i];
  438.     if(peername != NULLCHAR && peernamelen != NULL){
  439.         *peernamelen = min(up->peernamelen,*peernamelen);
  440.         memcpy(peername,up->peername,*peernamelen);
  441.     }
  442.     return i;
  443. }
  444. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  445.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  446.  * the len parameter.
  447.  */
  448. int
  449. recv_mbuf(s,bpp,len,flags,from,fromlen)
  450. int s;            /* Socket index */
  451. struct mbuf **bpp;    /* Place to stash receive buffer */
  452. int len;        /* Maximum length to read (0 implies all) */
  453. int flags;        /* Unused; will control out-of-band data, etc */
  454. char *from;        /* Peer address (only for datagrams) */
  455. int *fromlen;        /* Length of peer address */
  456. {
  457.     register struct usock *up;
  458.     int cnt;
  459.     union cb cb;
  460.     struct socket fsocket;
  461.     union sp remote;
  462.     struct ip ip;
  463.     struct mbuf *bp;
  464.  
  465.     if((up = itop(s)) == NULLUSOCK){
  466.         errno = EBADF;
  467.         return -1;
  468.     }
  469.     switch(up->type){
  470.     case TYPE_TCP:
  471.         while((cb.tcb = up->cb.tcb) != NULLTCB
  472.          && cb.tcb->r_upcall != trdiscard
  473.                  && (cnt = recv_tcp(cb.tcb,&bp,len)) == -1){
  474.             if(up->noblock){
  475.                 errno = EWOULDBLOCK;
  476.                 return -1;
  477.             } else if(pwait(up) != 0){
  478.                 errno = EINTR;
  479.                 return -1;
  480.             }
  481.         }
  482.         if(cb.tcb == NULLTCB){
  483.             /* Connection went away */
  484.             errno = ENOTCONN;
  485.             return -1;
  486.         } else if(cb.tcb->r_upcall == trdiscard){
  487.             /* Receive shutdown has been done */
  488.             errno = ENOTCONN;    /* CHANGE */
  489.             return -1;
  490.         }
  491.         break;
  492.     case TYPE_UDP:
  493.         while((cb.udp = up->cb.udp) != NULLUDP
  494.         && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  495.             if(up->noblock){
  496.                 errno = EWOULDBLOCK;
  497.                 return -1;
  498.             } else if(pwait(up) != 0){
  499.                 errno = EINTR;
  500.                 return -1;
  501.             }
  502.         }
  503.         if(cb.udp == NULLUDP){
  504.             /* Connection went away */
  505.             errno = ENOTCONN;
  506.             return -1;
  507.         }
  508.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  509.             remote.in = (struct sockaddr_in *)from;
  510.             remote.in->sin_family = AF_INET;
  511.             remote.in->sin_addr.s_addr = fsocket.address;
  512.             remote.in->sin_port = fsocket.port;
  513.             *fromlen = SOCKSIZE;
  514.         }
  515.         break;
  516.     case TYPE_RAW:
  517.         while((cb.rip = up->cb.rip) != NULLRIP
  518.          && cb.rip->rcvq == NULLBUF){
  519.             if(up->noblock){
  520.                 errno = EWOULDBLOCK;
  521.                 return -1;
  522.             } else if(pwait(up) != 0){
  523.                 errno = EINTR;
  524.                 return -1;
  525.             }
  526.         }
  527.         if(cb.rip == NULLRIP){
  528.             /* Connection went away */
  529.             errno = ENOTCONN;
  530.             return -1;
  531.         }
  532.         bp = dequeue(&cb.rip->rcvq);
  533.         ntohip(&ip,&bp);
  534.         cnt = len_mbuf(bp);
  535.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  536.             remote.in = (struct sockaddr_in *)from;
  537.             remote.in->sin_family = AF_INET;
  538.             remote.in->sin_addr.s_addr = ip.source;
  539.             remote.in->sin_port = 0;
  540.             *fromlen = SOCKSIZE;
  541.         }
  542.         break;
  543. #ifdef    AX25
  544.     case TYPE_AX25I:
  545.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  546.          && (bp = recv_ax25(cb.ax25,len)) == NULLBUF){
  547.             if(up->noblock){
  548.                 errno = EWOULDBLOCK;
  549.                 return -1;
  550.             } else if(pwait(up) != 0){
  551.                 errno = EINTR;
  552.                 return -1;
  553.             }
  554.         }
  555.         if(cb.ax25 == NULLAX25){
  556.             /* Connection went away */
  557.             errno = ENOTCONN;
  558.             return -1;
  559.         }
  560.         break;
  561.     case TYPE_AX25UI:
  562.         while(s == axui_sock && bcq == NULLBUF){
  563.             if(up->noblock){
  564.                 errno = EWOULDBLOCK;
  565.                 return -1;
  566.             } else if(pwait(&bcq) != 0){
  567.                 errno = EINTR;
  568.                 return -1;
  569.             }
  570.         }
  571.         if(s != axui_sock){
  572.             errno = ENOTCONN;
  573.             return -1;
  574.         }
  575.         bp = dequeue(&bcq);
  576.  
  577.         if(from != NULLCHAR && fromlen != NULLINT && *fromlen >= SOCKSIZE){
  578.             pullup(&bp,(char *)from,SOCKSIZE);
  579.             *fromlen = SOCKSIZE;
  580.         } else {
  581.             pullup(&bp,NULLCHAR,SOCKSIZE);
  582.         }
  583.         break;
  584. #endif
  585.     }
  586.     if(bpp != NULLBUFP)
  587.         *bpp = bp;
  588.     return cnt;
  589. }
  590. /* Low level send routine; user supplies mbuf for transmission. More
  591.  * efficient than send() or sendto(), the higher level interfaces.
  592.  * The "to" and "tolen" parameters are ignored on connection-oriented
  593.  * sockets.
  594.  *
  595.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  596.  */
  597. int
  598. send_mbuf(s,bp,flags,to,tolen)
  599. int s;            /* Socket index */
  600. struct mbuf *bp;    /* Buffer to send */
  601. int flags;        /* not currently used */
  602. char *to;        /* Destination, only for datagrams */
  603. int tolen;        /* Length of destination */
  604. {
  605.     register struct usock *up;
  606.     union cb cb;
  607.     union sp local,remote;
  608.     struct socket lsock,fsock;
  609.     int cnt;
  610.  
  611.     if((up = itop(s)) == NULLUSOCK){
  612.         free_p(bp);
  613.         errno = EBADF;
  614.         return -1;
  615.     }
  616.     if(up->name == NULLCHAR){
  617.         /* Automatic local name assignment for datagram sockets */
  618.         switch(up->type){
  619.         case TYPE_UDP:
  620.         case TYPE_RAW:
  621.             autobind(s,AF_INET);
  622.             break;
  623.         case TYPE_AX25UI:
  624.             autobind(s,AF_AX25);
  625.             break;
  626.         default:
  627.             free_p(bp);
  628.             errno = ENOTCONN;
  629.             return -1;
  630.         }
  631.     }
  632.     cnt = len_mbuf(bp);
  633.     switch(up->type){
  634.     case TYPE_TCP:
  635.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  636.             free_p(bp);
  637.             errno = ENOTCONN;
  638.             return -1;
  639.         }        
  640.         cnt = send_tcp(cb.tcb,bp);
  641.  
  642.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  643.          cb.tcb->sndcnt > cb.tcb->window){
  644.             /* Send queue is full */
  645.             if(up->noblock){
  646.                 errno = EWOULDBLOCK;
  647.                 return -1;
  648.             } else if(pwait(up) != 0){
  649.                 errno = EINTR;
  650.                 return -1;
  651.             }
  652.         }
  653.          if(cb.tcb == NULLTCB){
  654.             errno = ENOTCONN;
  655.             return -1;
  656.         }
  657.         break;
  658.     case TYPE_UDP:
  659.         local.in = (struct sockaddr_in *)up->name;
  660.         lsock.address = local.in->sin_addr.s_addr;
  661.         lsock.port = local.in->sin_port;
  662.         if(to != NULLCHAR)
  663.             remote.in = (struct sockaddr_in *)to;
  664.         else if(up->peername != NULLCHAR)
  665.             remote.in = (struct sockaddr_in *)up->peername;
  666.         else {
  667.             errno = ENOTCONN;
  668.             return -1;
  669.         }    
  670.         fsock.address = remote.in->sin_addr.s_addr;
  671.         fsock.port = remote.in->sin_port;
  672.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  673.         break;
  674.     case TYPE_RAW:
  675.         local.in = (struct sockaddr_in *)up->name;
  676.         if(to != NULLCHAR)
  677.             remote.in = (struct sockaddr_in *)to;
  678.         else if(up->peername != NULLCHAR)
  679.             remote.in = (struct sockaddr_in *)up->peername;
  680.         else {
  681.             errno = ENOTCONN;
  682.             return -1;
  683.         }    
  684.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  685.             up->cb.rip->protocol,0,0,bp,0,0,0);
  686.         break;
  687. #ifdef    AX25
  688.     case TYPE_AX25I:
  689.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  690.             free_p(bp);
  691.             errno = ENOTCONN;
  692.             return -1;
  693.         }
  694.         send_ax25(cb.ax25,bp,PID_NO_L3);
  695.  
  696.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  697.          len_q(cb.ax25->txq) > cb.ax25->window){
  698.             if(up->noblock){
  699.                 errno = EWOULDBLOCK;
  700.                 return -1;
  701.             } else if(pwait(up) != 0){
  702.                 errno = EINTR;
  703.                 return -1;
  704.             }
  705.         }
  706.         if(cb.ax25 == NULLAX25){
  707.             errno = EBADF;
  708.             return -1;
  709.         }
  710.         break;
  711.     case TYPE_AX25UI:
  712.         local.ax = (struct sockaddr_ax *)up->name;
  713.         if(to != NULLCHAR)
  714.             remote.ax = (struct sockaddr_ax *)to;
  715.         else if(up->peername != NULLCHAR)
  716.             remote.ax = (struct sockaddr_ax *)up->peername;
  717.         else {
  718.             errno = ENOTCONN;
  719.             return -1;
  720.         }
  721.         ax_output(NULLIF,(char *)&remote.ax->ax25_addr,
  722.          (char *)&local.ax->ax25_addr,PID_NO_L3,bp);
  723.         break;
  724. #endif
  725.     }    
  726.     return cnt;
  727. }
  728. /* Higher-level receive routine, intended for connection-oriented sockets.
  729.  * Can be used with datagram sockets, although the sender id is lost.
  730.  */
  731. int
  732. recv(s,buf,len,flags)
  733. int s;        /* Socket index */
  734. char *buf;    /* User buffer */
  735. int len;    /* Max length to receive */
  736. int flags;    /* Unused; will eventually select oob data, etc */
  737. {
  738.     struct mbuf *bp;
  739.     int cnt;
  740.  
  741.     if(len == 0)
  742.         return 0;    /* Otherwise would be interp as "all" */
  743.  
  744.     cnt = recv_mbuf(s,&bp,len,flags,NULLCHAR,(int *)NULL);
  745.     if(cnt > 0){
  746.         cnt = min(cnt,len);
  747.         pullup(&bp,buf,cnt);
  748.         free_p(bp);
  749.     }
  750.     return cnt;
  751. }
  752. /* Higher level receive routine, intended for datagram sockets. Can also
  753.  * be used for connection-oriented sockets, although from and fromlen are
  754.  * ignored.
  755.  */
  756. int
  757. recvfrom(s,buf,len,flags,from,fromlen)
  758. int s;        /* Socket index */
  759. char *buf;    /* User buffer */
  760. int len;    /* Maximum length */
  761. int flags;    /* Unused; will eventually select oob data, etc */
  762. char *from;    /* Source address, only for datagrams */
  763. int *fromlen;    /* Length of source address */
  764. {
  765.     struct mbuf *bp;
  766.     register int cnt;
  767.  
  768.     cnt = recv_mbuf(s,&bp,len,flags,from,fromlen);
  769.     if(cnt > 0){
  770.         cnt = min(cnt,len);
  771.         pullup(&bp,buf,cnt);
  772.         free_p(bp);
  773.     }
  774.     return cnt;
  775. }
  776. /* High level send routine */
  777. int
  778. send(s,buf,len,flags)
  779. int s;        /* Socket index */
  780. char *buf;    /* User buffer */
  781. int len;    /* Length of buffer */
  782. int flags;    /* Unused; will eventually select oob data, etc */
  783. {
  784.     register struct mbuf *bp;
  785.     struct sockaddr sock;
  786.     int i = sizeof(sock);
  787.  
  788.     if(getpeername(s,(char *)&sock,&i) == -1)
  789.         return -1;
  790.     bp = qdata(buf,len);
  791.     return send_mbuf(s,bp,flags,(char *)&sock,i);
  792. }
  793. /* High level send routine, intended for datagram sockets. Can be used on
  794.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  795.  */
  796. int
  797. sendto(s,buf,len,flags,to,tolen)
  798. int s;        /* Socket index */
  799. char *buf;    /* User buffer */
  800. int len;    /* Length of buffer */
  801. int flags;    /* Unused; will eventually select oob data, etc */
  802. char *to;    /* Destination, only for datagrams */
  803. int tolen;    /* Length of destination */
  804. {
  805.     register struct mbuf *bp;
  806.  
  807.     bp = qdata(buf,len);
  808.     return send_mbuf(s,bp,flags,to,tolen);
  809. }
  810. /* Return local name passed in an earlier bind() call */
  811. int
  812. getsockname(s,name,namelen)
  813. int s;        /* Socket index */
  814. char *name;    /* Place to stash name */
  815. int *namelen;    /* Length of same */
  816. {
  817.     register struct usock *up;
  818.  
  819.     if((up = itop(s)) == NULLUSOCK){
  820.         errno = EBADF;
  821.         return -1;
  822.     }
  823.     if(name == NULLCHAR || namelen == (int *)NULL){
  824.         errno = EFAULT;
  825.         return -1;
  826.     }
  827.     if(up->name == NULLCHAR){
  828.         /* Not bound yet */
  829.         *namelen = 0;
  830.         return 0;
  831.     }
  832.     if(up->name != NULLCHAR){
  833.         *namelen = min(*namelen,up->namelen);
  834.         memcpy(name,up->name,*namelen);
  835.     }
  836.     return 0;
  837. }
  838. /* Get remote name, returning result of earlier connect() call. */
  839. int
  840. getpeername(s,peername,peernamelen)
  841. int s;            /* Socket index */
  842. char *peername;        /* Place to stash name */
  843. int *peernamelen;    /* Length of same */
  844. {
  845.     register struct usock *up;
  846.  
  847.     if((up = itop(s)) == NULLUSOCK){
  848.         errno = EBADF;
  849.         return -1;
  850.     }
  851.     if(up->peername == NULLCHAR){
  852.         errno = ENOTCONN;
  853.         return -1;
  854.     }
  855.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  856.         errno = EFAULT;
  857.         return -1;
  858.     }
  859.     *peernamelen = min(*peernamelen,up->peernamelen);
  860.     memcpy(peername,up->peername,*peernamelen);
  861.     return 0;
  862. }
  863. /* Return length of protocol queue, either send or receive. */
  864. int
  865. socklen(s,rtx)
  866. int s;        /* Socket index */
  867. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  868. {
  869.     register struct usock *up;
  870.  
  871.     if((up = itop(s)) == NULLUSOCK){
  872.         errno = EBADF;
  873.         return -1;
  874.     }
  875.     if(up->cb.p == NULLCHAR){
  876.         errno = ENOTCONN;
  877.         return -1;
  878.     }
  879.     if(rtx < 0 || rtx > 1){
  880.         errno = EINVAL;
  881.         return -1;
  882.     }
  883.     switch(up->type){
  884.     case TYPE_TCP:
  885.         switch(rtx){
  886.         case 0:
  887.             return up->cb.tcb->rcvcnt;
  888.         case 1:
  889.             return up->cb.tcb->sndcnt;
  890.         }
  891.     case TYPE_UDP:
  892.         switch(rtx){
  893.         case 0:
  894.             return up->cb.udp->rcvcnt;
  895.         case 1:
  896.             return 0;
  897.         }
  898. #ifdef    AX25
  899.     case TYPE_AX25I:
  900.         switch(rtx){
  901.         case 0:
  902.             return len_mbuf(up->cb.ax25->rxq);
  903.         case 1:    /* Number of packets, not bytes */
  904.             return len_q(up->cb.ax25->txq);
  905.         }
  906.     case TYPE_AX25UI:
  907.         /* TO BE IMPLEMENTED */
  908.         return 0;
  909. #endif
  910.     case TYPE_RAW:
  911.         return len_q(up->cb.rip->rcvq);
  912.     }
  913.     /*NOTREACHED*/
  914. }
  915. /* Force retransmission. Valid only for connection-oriented sockets. */
  916. int
  917. sockkick(s)
  918. int s;    /* Socket index */
  919. {
  920.     register struct usock *up;
  921.  
  922.     if((up = itop(s)) == NULLUSOCK){
  923.         errno = EBADF;
  924.         return -1;
  925.     }
  926.     if(up->cb.p == NULLCHAR){
  927.         errno = ENOTCONN;
  928.         return -1;
  929.     }
  930.     switch(up->type){
  931.     case TYPE_TCP:
  932.         kick_tcp(up->cb.tcb);
  933.         break;
  934. #ifdef    AX25
  935.     case TYPE_AX25I:
  936.         kick_ax25(up->cb.ax25);
  937.         break;
  938. #endif
  939.     default:
  940.         /* Datagram sockets can't be kicked */
  941.         errno = EOPNOTSUPP;
  942.         return -1;
  943.     }
  944.     return 0;
  945. }
  946.  
  947. /* Get state of protocol. Valid only for connection-oriented sockets. */
  948. char *
  949. sockstate(s)
  950. int s;        /* Socket index */
  951. {
  952.     register struct usock *up;
  953.  
  954.     if((up = itop(s)) == NULLUSOCK){
  955.         errno = EBADF;
  956.         return NULLCHAR;
  957.     }
  958.     if(up->cb.p == NULLCHAR){
  959.         errno = ENOTCONN;
  960.         return NULLCHAR;
  961.     }
  962.     switch(up->type){
  963.     case TYPE_TCP:
  964.         return Tcpstates[up->cb.tcb->state];
  965. #ifdef    AX25
  966.     case TYPE_AX25I:
  967.         return Ax25states[up->cb.ax25->state];
  968. #endif
  969.     default:
  970.         /* Datagram sockets don't have state */
  971.         errno = EOPNOTSUPP;
  972.         return NULLCHAR;
  973.     }
  974.     /*NOTREACHED*/
  975. }
  976. /* Change owner of socket, return previous owner */
  977. struct proc *
  978. sockowner(s,newowner)
  979. int s;            /* Socket index */
  980. struct proc *newowner;    /* Process table address of new owner */
  981. {
  982.     register struct usock *up;
  983.     struct proc *pp;
  984.  
  985.     if((up = itop(s)) == NULLUSOCK){
  986.         errno = EBADF;
  987.         return NULLPROC;
  988.     }
  989.     pp = up->owner;
  990.     if(newowner != NULLPROC)
  991.         up->owner = newowner;
  992.     return pp;
  993. }
  994. /* Close down a socket three ways. Type 0 means "no more receives"; this
  995.  * replaces the incoming data upcall with a routine that discards further
  996.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  997.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  998.  * as "abort the connection".
  999.  */
  1000. int
  1001. shutdown(s,how)
  1002. int s;        /* Socket index */
  1003. int how;    /* (see above) */
  1004. {
  1005.     register struct usock *up;
  1006.  
  1007.     if((up = itop(s)) == NULLUSOCK){
  1008.         errno = EBADF;
  1009.         return -1;
  1010.     }
  1011.     if(up->cb.p == NULLCHAR){
  1012.         errno = ENOTCONN;
  1013.         return -1;
  1014.     }
  1015.     switch(up->type){
  1016.     case TYPE_TCP:
  1017.         switch(how){
  1018.         case 0:    /* No more receives -- replace upcall */
  1019.             up->cb.tcb->r_upcall = trdiscard;
  1020.             break;
  1021.         case 1:    /* Send EOF */
  1022.             close_tcp(up->cb.tcb);
  1023.             break;
  1024.         case 2:    /* Blow away TCB */
  1025.             reset_tcp(up->cb.tcb);
  1026.             up->cb.tcb = NULLTCB;
  1027.             break;
  1028.         }
  1029.         break;
  1030. #ifdef    AX25
  1031.     case TYPE_AX25I:
  1032.         switch(how){
  1033.         case 0:
  1034.         case 1:    /* Attempt regular disconnect */
  1035.             disc_ax25(up->cb.ax25);
  1036.             break;
  1037.         case 2: /* Blow it away */
  1038.             reset_ax25(up->cb.ax25);
  1039.             up->cb.ax25 = NULLAX25;
  1040.             break;
  1041.         }
  1042.         break;        
  1043. #endif
  1044.     case TYPE_RAW:
  1045.         close_s(s);
  1046.         break;
  1047.     default:
  1048.         errno = EOPNOTSUPP;
  1049.         return -1;
  1050.     }
  1051.     psignal(up,0);
  1052.     return 0;
  1053. }
  1054. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1055.  * TCP socket, if possible
  1056.  */
  1057. int
  1058. close_s(s)
  1059. int s;        /* Socket index */
  1060. {
  1061.     register struct usock *up;
  1062.  
  1063.     if((up = itop(s)) == NULLUSOCK){
  1064.         errno = EBADF;
  1065.         return -1;
  1066.     }
  1067.     switch(up->type){
  1068.     case TYPE_TCP:
  1069.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1070.             up->cb.tcb->r_upcall = trdiscard;
  1071.             /* Tell the CLOSED upcall there's no more socket */
  1072.             up->cb.tcb->user = -1;
  1073.             close_tcp(up->cb.tcb);
  1074.         }
  1075.         break;
  1076.     case TYPE_UDP:
  1077.         if(up->cb.udp != NULLUDP){
  1078.             del_udp(up->cb.udp);
  1079.         }
  1080.         break;
  1081. #ifdef    AX25
  1082.     case TYPE_AX25I:
  1083.         if(up->cb.ax25 != NULLAX25){
  1084.             /* Tell the CLOSED upcall there's no more socket */
  1085.             up->cb.ax25->user = -1;
  1086.             disc_ax25(up->cb.ax25);
  1087.         }
  1088.         break;
  1089.     case TYPE_AX25UI:
  1090.         axui_sock = -1;
  1091.         free_q(&bcq);
  1092.         psignal(&bcq,0);    /* Unblock any reads */
  1093.         break;
  1094. #endif
  1095.     case TYPE_RAW:
  1096.         del_ip(up->cb.rip);
  1097.         break;
  1098.     default:
  1099.         errno = EOPNOTSUPP;
  1100.         return -1;
  1101.     }
  1102.     free(up->name);
  1103.     free(up->peername);
  1104.  
  1105.     up->cb.p = NULLCHAR;
  1106.     up->name = up->peername = NULLCHAR;
  1107.     up->type = NOTUSED;
  1108.     psignal(up,0);    /* Wake up anybody doing an accept() or recv() */
  1109.     return 0;
  1110. }
  1111. /* Return ASCII string giving reason for connection closing */
  1112. char *
  1113. sockerr(s)
  1114. int s;    /* Socket index */
  1115. {
  1116.     register struct usock *up;
  1117.  
  1118.     if((up = itop(s)) == NULLUSOCK){
  1119.         errno = EBADF;
  1120.         return Badsocket;
  1121.     }
  1122.     switch(up->type){
  1123. #ifdef    AX25
  1124.     case TYPE_AX25I:
  1125.         if(up->cb.ax25 != NULLAX25)
  1126.             return NULLCHAR;    /* nothing wrong */
  1127.         return Axreasons[up->errcodes[0]];
  1128. #endif
  1129.     case TYPE_TCP:
  1130.         if(up->cb.tcb != NULLTCB)
  1131.             return NULLCHAR;    /* nothing wrong */        
  1132.         return Tcpreasons[up->errcodes[0]];
  1133.     default:
  1134.         errno = EOPNOTSUPP;    /* not yet, anyway */
  1135.         return NULLCHAR;
  1136.     }
  1137. }
  1138. /* End of user socket primitives, begin user utility subroutines */
  1139.  
  1140. /* Receive a newline-terminated line from a socket, returning # chars read */
  1141. int
  1142. recvline(s,buf,len)
  1143. int s;        /* Socket index */
  1144. char *buf;    /* User buffer */
  1145. unsigned len;    /* Length of buffer */
  1146. {
  1147.     char c;
  1148.     int cnt = 0;
  1149.  
  1150.     while(len-- != 0){
  1151.         if(recv(s,&c,1,0) != 1){
  1152.             *buf = '\0';
  1153.             return -1;
  1154.         }
  1155.         *buf++ = c;
  1156.         cnt++;
  1157.         if(uchar(c) == '\n')
  1158.             break;
  1159.     }
  1160.     if(len != 0)
  1161.         *buf = '\0';
  1162.     return cnt;
  1163. }
  1164. /* Do printf on a user socket */
  1165. #if    defined(__STDC__) || defined(__TURBOC__)
  1166. int
  1167. usprintf(int s,char *fmt,...)
  1168. {
  1169.     register struct mbuf *bp;
  1170.     int len;
  1171.     va_list args;
  1172.  
  1173.     va_start(args,fmt);
  1174.     bp = alloc_mbuf(200);
  1175.     len = vsprintf(bp->data,fmt,args);
  1176.     bp->cnt = strlen(bp->data);
  1177.     send_mbuf(s,bp,0,NULLCHAR,0);
  1178.     va_end(args);
  1179.     return len;
  1180. }
  1181. #else
  1182. /*VARARGS*/
  1183. int
  1184. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6)
  1185. int s;            /* Socket index */
  1186. char *fmt;        /* Message format */
  1187. int arg1,arg2,arg3;    /* Arguments */
  1188. int arg4,arg5,arg6;
  1189. {
  1190.     register struct mbuf *bp;
  1191.     int len;
  1192.  
  1193.     bp = alloc_mbuf(200);
  1194.     len = sprintf(bp->data,fmt,arg1,arg2,arg3,arg4,arg5,arg6);
  1195.     bp->cnt = strlen(bp->data);
  1196.     send_mbuf(s,bp,0,NULLCHAR,0);
  1197.     return len;
  1198. }
  1199. #endif
  1200. /* Convert a socket (address + port) to an ascii string of the form
  1201.  * aaa.aaa.aaa.aaa:ppppp
  1202.  */
  1203. char *
  1204. psocket(s)
  1205. struct sockaddr *s;    /* Pointer to structure to decode */
  1206. {
  1207.     char tmp[11];
  1208.     static char buf[30];
  1209.     union sp sp;
  1210.     struct socket socket;
  1211.  
  1212.     switch(s->sa_family){
  1213.     case AF_INET:
  1214.         sp.in = (struct sockaddr_in *)s;
  1215.         socket.address = sp.in->sin_addr.s_addr;
  1216.         socket.port = sp.in->sin_port;
  1217.         strcpy(buf,pinet(&socket));
  1218.         break;
  1219. #ifdef    AX25
  1220.     case AF_AX25:
  1221.         sp.ax = (struct sockaddr_ax *)s;
  1222.         pax25(tmp,&sp.ax->ax25_addr);
  1223.         sprintf(buf,"%s on %s",tmp,sp.ax->iface);
  1224.         break;
  1225. #endif
  1226.     }
  1227.     return buf;
  1228. }
  1229. char *
  1230. pinet(s)
  1231. struct socket *s;
  1232. {
  1233.     static char buf[30];
  1234.  
  1235.     sprintf(buf,"%s:%u",inet_ntoa(s->address),s->port);
  1236.     return buf;
  1237. }
  1238. /* Read a character from a socket with stream buffering */
  1239. int
  1240. recvchar(s,bpp)
  1241. int s;            /* Socket index */
  1242. struct mbuf **bpp;    /* User-supplied buffer pointer */
  1243. {
  1244.     char c;
  1245.  
  1246.     if(*bpp == NULLBUF)
  1247.         recv_mbuf(s,bpp,0,0,NULLCHAR,0);    /* Replenish */
  1248.  
  1249.     if(pullup(bpp,&c,1) != 1)
  1250.         return -1;
  1251.     return uchar(c);
  1252. }
  1253. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1254. void
  1255. freesock(pp)
  1256. struct proc *pp;
  1257. {
  1258.     register struct usock *up;
  1259.     register int i;
  1260.  
  1261.     for(i=0;i < Nusock;i++){
  1262.         up = &Usock[i];
  1263.         if(up->type != NOTUSED && up->owner == pp)
  1264.             shutdown(i,2);
  1265.     }
  1266. }
  1267.  
  1268. /* End of user utility subroutines, start internal subroutines */
  1269.  
  1270. /* Raw IP receive upcall routine */
  1271. static void
  1272. rip_recv(rp)
  1273. struct raw_ip *rp;
  1274. {
  1275.     psignal(itop(rp->user),1);
  1276.     pwait(NULL);
  1277. }
  1278.  
  1279. /* UDP receive upcall routine */
  1280. static void
  1281. s_urcall(udp,cnt)
  1282. struct udp_cb *udp;
  1283. int cnt;
  1284. {
  1285.     psignal(itop(udp->user),1);
  1286.     pwait(NULL);
  1287. }
  1288. /* TCP receive upcall routine */
  1289. static void
  1290. s_trcall(tcb,cnt)
  1291. struct tcb *tcb;
  1292. int cnt;
  1293. {
  1294.     /* Wake up anybody waiting for data, and let them run */
  1295.     psignal(itop(tcb->user),1);
  1296.     pwait(NULL);
  1297. }
  1298. /* TCP transmit upcall routine */
  1299. static void
  1300. s_ttcall(tcb,cnt)
  1301. struct tcb *tcb;
  1302. int cnt;
  1303. {
  1304.     /* Wake up anybody waiting to send data, and let them run */
  1305.     psignal(itop(tcb->user),1);
  1306.     pwait(NULL);
  1307. }
  1308. /* TCP state change upcall routine */
  1309. static void
  1310. s_tscall(tcb,old,new)
  1311. struct tcb *tcb;
  1312. int old,new;
  1313. {
  1314.     int s,ns;
  1315.     struct usock *up,*nup,*oup;
  1316.     union sp sp;
  1317.  
  1318.     s = tcb->user;
  1319.     oup = up = itop(s);
  1320.  
  1321.     switch(new){
  1322.     case CLOSED:
  1323.         /* Clean up. If the user has already closed the socket,
  1324.          * then up will be null (s was set to -1 by the close routine).
  1325.          * If not, then this is an abnormal close (e.g., a reset)
  1326.          * and clearing out the pointer in the socket structure will
  1327.          * prevent any further operations on what will be a freed
  1328.          * control block. Also wake up anybody waiting on events
  1329.          * related to this tcb so they will notice it disappearing.
  1330.          */
  1331.         if(up != NULLUSOCK){
  1332.             up->cb.tcb = NULLTCB;
  1333.             up->errcodes[0] = tcb->reason;
  1334.             up->errcodes[1] = tcb->type;
  1335.             up->errcodes[2] = tcb->code;
  1336.         }
  1337.         del_tcp(tcb);
  1338.         break;
  1339.     case SYN_RECEIVED:
  1340.         /* Handle an incoming connection. If this is a server TCB,
  1341.          * then we're being handed a "clone" TCB and we need to
  1342.          * create a new socket structure for it. In either case,
  1343.          * find out who we're talking to and wake up the guy waiting
  1344.          * for the connection.
  1345.          */
  1346.         if(tcb->flags.clone){
  1347.             /* Clone the socket */
  1348.             ns = socket(AF_INET,SOCK_STREAM,0);
  1349.             nup = &Usock[ns];
  1350.             memcpy((char *)nup,(char *)up,sizeof(struct usock));
  1351.             tcb->user = ns;
  1352.             nup->cb.tcb = tcb;
  1353.             /* Allocate new memory for the name areas */
  1354.             nup->name = malloc(SOCKSIZE);
  1355.             nup->peername = malloc(SOCKSIZE);
  1356.             /* Store the new socket # in the old one */
  1357.             up->rdysock = ns;
  1358.             up = nup;
  1359.             s = ns;
  1360.         } else {
  1361.             /* Allocate space for the peer's name */
  1362.             up->peername = malloc(SOCKSIZE);
  1363.             /* Store the old socket # in the old socket */
  1364.             up->rdysock = s;
  1365.         }
  1366.         /* Load the addresses. Memory for the name has already
  1367.          * been allocated, either above or in the original bind.
  1368.          */
  1369.         sp.p = up->name;
  1370.         sp.in->sin_family = AF_INET;
  1371.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1372.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1373.         up->namelen = SOCKSIZE;
  1374.  
  1375.         sp.p = up->peername;
  1376.         sp.in->sin_family = AF_INET;
  1377.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1378.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1379.         up->peernamelen = SOCKSIZE;
  1380.  
  1381.         /* Wake up the guy accepting it, and let him run */
  1382.         psignal(oup,1);
  1383.         pwait(NULL);
  1384.         break;
  1385.     default:    /* Ignore all other state transitions */
  1386.         break;
  1387.     }
  1388.     psignal(up,0);    /* In case anybody's waiting */
  1389. }
  1390. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1391.  * close_s until the TCB disappears.
  1392.  */
  1393. static void
  1394. trdiscard(tcb,cnt)
  1395. struct tcb *tcb;
  1396. int cnt;
  1397. {
  1398.     struct mbuf *bp;
  1399.  
  1400.     recv_tcp(tcb,&bp,cnt);
  1401.     free_p(bp);
  1402. }
  1403. #ifdef    AX25
  1404. /* AX.25 receive upcall */
  1405. void
  1406. s_arcall(axp,cnt)
  1407. struct ax25_cb *axp;
  1408. int cnt;
  1409. {
  1410.     /* Wake up anyone waiting, and let them run */
  1411.     psignal(itop(axp->user),1);
  1412.     pwait(NULL);
  1413. }
  1414. /* AX.25 transmit upcall */
  1415. void
  1416. s_atcall(axp,cnt)
  1417. struct ax25_cb *axp;
  1418. int cnt;
  1419. {
  1420.     /* Wake up anyone waiting, and let them run */
  1421.     psignal(itop(axp->user),1);
  1422.     pwait(NULL);
  1423. }
  1424. /* AX25 state change upcall routine */
  1425. void
  1426. s_ascall(axp,old,new)
  1427. register struct ax25_cb *axp;
  1428. int old,new;
  1429. {
  1430.     int s;
  1431.     struct usock *up;
  1432.  
  1433.     s = axp->user;
  1434.     up = itop(s);
  1435.  
  1436.     switch(new){
  1437.     case DISCONNECTED:
  1438.         /* Clean up. If the user has already closed the socket,
  1439.          * then up will be null (s was set to -1 by the close routine).
  1440.          * If not, then this is an abnormal close (e.g., a reset)
  1441.          * and clearing out the pointer in the socket structure will
  1442.          * prevent any further operations on what will be a freed
  1443.          * control block. Also wake up anybody waiting on events
  1444.          * related to this block so they will notice it disappearing.
  1445.          */
  1446.         if(up != NULLUSOCK){
  1447.             up->errcodes[0] = axp->reason;
  1448.             up->cb.ax25 = NULLAX25;
  1449.         }
  1450.         del_ax25(axp);
  1451.         break;
  1452.     default:    /* Other transitions are ignored */
  1453.         break;
  1454.     }
  1455.     psignal(up,0);    /* In case anybody's waiting */
  1456. }
  1457. #endif
  1458.  
  1459. /* Verify address family and length according to the socket type */
  1460. static int
  1461. checkaddr(type,name,namelen)
  1462. char *name;
  1463. int type;
  1464. int namelen;
  1465. {
  1466.     register struct sockaddr *sp;
  1467.  
  1468.     sp = (struct sockaddr *)name;
  1469.     /* Verify length and address family according to protocol */
  1470.     switch(type){
  1471.     case TYPE_TCP:
  1472.     case TYPE_UDP:
  1473.         if(sp->sa_family != AF_INET
  1474.          || namelen != sizeof(struct sockaddr_in))
  1475.             return -1;
  1476.         break;
  1477.     case TYPE_AX25I:
  1478.     case TYPE_AX25UI:
  1479.         if(sp->sa_family != AF_AX25
  1480.          || namelen != sizeof(struct sockaddr_ax))
  1481.             return -1;
  1482.         break;
  1483.     }
  1484.     return 0;
  1485. }
  1486. /* Convert a socket index to an internal user socket structure pointer */
  1487. static struct usock *
  1488. itop(s)
  1489. register int s;    /* Socket index */
  1490. {
  1491.     register struct usock *up;
  1492.  
  1493.     if(s < 0 || s >= Nusock)
  1494.         return NULLUSOCK;
  1495.  
  1496.     up = &Usock[s];
  1497.  
  1498.     if(up->type == NOTUSED)
  1499.         return NULLUSOCK;
  1500.     return up;
  1501. }
  1502. /* Issue an automatic bind of a local address */
  1503. static void
  1504. autobind(s,af)
  1505. int s,af;
  1506. {
  1507.     struct sockaddr sockaddr;
  1508.     union sp sp;
  1509.  
  1510.     sp.p = (char *)&sockaddr;
  1511.     switch(af){
  1512.     case AF_INET:
  1513.         sp.in->sin_family = AF_INET;
  1514.         sp.in->sin_addr.s_addr = Ip_addr;
  1515.         sp.in->sin_port = Lport++;
  1516.         bind(s,sp.p,SOCKSIZE);
  1517.         break;
  1518. #ifdef    AX25
  1519.     case AF_AX25:
  1520.         sp.ax->sax_family = AF_AX25;
  1521.         memcpy(sp.ax->ax25_addr.call,Mycall.call,ALEN);
  1522.         sp.ax->ax25_addr.ssid = Mycall.ssid;
  1523.         bind(s,sp.p,SOCKSIZE);
  1524.         break;
  1525. #endif
  1526.     }
  1527. }
  1528.  
  1529.  
  1530.